#pragma once
#include <unordered_map>
#include "Common.hpp"
#include "Connection.hpp"
#include "Inet_host.hpp"
#include "Logger.hpp"
#include "Socket.hpp"
#include "Epoller.hpp"

using connection_t = std::shared_ptr<Connection>;

class Reactor
{
    const static int epoll_num = 64;

public:
    Reactor() : _epollor(std::make_unique<Epollor>()), _isrunning(false)
    {
        _epollor->Iint();
    }
    ~Reactor()
    {
    }
    void Dispatcher(int num)
    {
        for (int i = 0; i < num; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;
            // 根据不同事件派发
            if (events & EPOLLERR || events & EPOLLHUP)
            {
                events = (EPOLLIN | EPOLLOUT);
            }
            if (events & EPOLLIN && IsConnectionExists(fd))
            {
                _connections[fd]->Recver();
            }
            if (events & EPOLLOUT && IsConnectionExists(fd))
            {
                _connections[fd]->Sender();
            }
        }
    }
     void DebugPrint()
    {
        std::cout << "Epoller 管理的fd: ";
        for (auto &iter : _connections)
        {
            std::cout << iter.first << " ";
        }
        std::cout << std::endl;
    }
    void LoopOnce(int timeout)
    {
        int n = _epollor->Wait(_revs, epoll_num, timeout);
        Dispatcher(n);
    }
    void Loop()
    {
        _isrunning = true;
        int timeout = -1;
        while (true)
        {
            LoopOnce(timeout);
            DebugPrint();
        }
        _isrunning = false;
    }
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
    void EnableReadWrite(int sockfd, bool EableRead, bool EableWrite)
    {
        if (IsConnectionExists(sockfd))
        {
            uint32_t events = (EableRead ? EPOLLIN : 0) | (EableWrite ? EPOLLOUT : 0) | EPOLLET;
            _connections[sockfd]->SetEvent(events);
            _epollor->Update(sockfd,events);
        }
    }
    void InsertConnection(connection_t con)
    {
          LOG(LogLevel::DEBUG)<<"Insert Recver1";
        // 检查是否在队列里
        if (!IsConnectionExists(con->Fd()))
        {
            LOG(LogLevel::DEBUG)<<"Insert Recver2";
            // 1.加入队列
            _connections[con->Fd()] = con;
            // 2.写透内核
            _epollor->Add(con->Fd(), con->GetEvents());
            // 3.设置关联关系
            con->SetOwner(this);
            LOG(LogLevel::DEBUG) << "add connection success: " << con->Fd();
        }
    }
    void DelConnection(int sockfd)
    {
        if(IsConnectionExists(sockfd))
        {
            _epollor->Del(sockfd);
            _connections[sockfd]->Close();
            _connections.erase(sockfd);
        }
    }

private:
    std::unique_ptr<Epollor> _epollor;                  // 创建epoll模型
    std::unordered_map<int, connection_t> _connections; // 管理所有链接
    bool _isrunning;
    // epollor 内核管理，wait时自动内置
    struct epoll_event _revs[epoll_num];
};